import React from "react";
import deepClone from "deep-clone";
import { Modal, Table, Space, Button, Tag, TableProps } from "antd";
import {
  PlusCircleOutlined,
  EditOutlined,
  DeleteOutlined,
} from "@ant-design/icons";
import TreeNodeForm from "./TreeNodeForm";
import { InnerField, Field } from "src/utils/interface";

import globalStyles from "src/public/css/index.scss";

const { useState, useEffect, useCallback } = React;

interface TreeData extends InnerField {
  key: string;
  innerFields: TreeData[];
}

interface Props {
  fieldData: Field;
  visible: boolean;
  setVisible: (visible: boolean) => void;
  onChange: (value: any) => void;
}

const InnerFieldsTree: React.FC<Props> = (props) => {
  const [treeData, setTreeData] = useState({ key: "0" } as TreeData);
  const [expandedRowKeys, setExpandedRowKeys] = useState([] as string[]);

  const [curEditType, setCurEditType] = useState("add");
  const [curEditKey, setCurEditKey] = useState("");
  const [curEditVisible, setCurEditVisible] = useState(false);
  const [curEditData, setCurEditData] = useState({} as TreeData);

  const tableProps: TableProps<TreeData> = {
    bordered: true,
    dataSource: [treeData],
    className: (globalStyles as any).tableTdPadding,
    // rowKey: "name",
    columns: [
      {
        title: "Name",
        dataIndex: "name",
        width: 150,
      },
      {
        title: "Type",
        dataIndex: "type",
        width: 120,
        render: (value, record) => {
          let type = value;
          if (value === "list") {
            type =
              record.itemType === "list"
                ? `${record.itemType2}[][]`
                : `${record.itemType}[]`;
          }
          return <Tag color="blue">{type}</Tag>;
        },
      },
      {
        title: "Description",
        dataIndex: "description",
        width: 300,
      },
      {
        title: "Operations",
        width: 150,
        render: (value, record) => (
          <Space>
            {(record.type === "struct" ||
              record.itemType === "struct" ||
              record.itemType2 === "struct") && (
              <Button
                type="primary"
                shape="circle"
                icon={<PlusCircleOutlined />}
                onClick={() => {
                  setCurEditType("add");
                  setCurEditKey(record.key);
                  setCurEditData({} as TreeData);
                  setCurEditVisible(true);
                }}
              />
            )}

            {record.key?.split("-").length > 1 && (
              <>
                <Button
                  shape="circle"
                  icon={<EditOutlined />}
                  onClick={() => {
                    setCurEditType("edit");
                    setCurEditKey(record.key);
                    setCurEditData(record);
                    setCurEditVisible(true);
                  }}
                />
                <Button
                  shape="circle"
                  danger
                  icon={<DeleteOutlined />}
                  onClick={() => {
                    deleteTreeNode(record.key);
                    setCurEditKey(record.key);
                  }}
                />
              </>
            )}
          </Space>
        ),
      },
    ],
    expandable: {
      childrenColumnName: "innerFields",
      defaultExpandAllRows: true,
      expandedRowKeys,
      onExpand: (expanded, record) => {
        if (expanded) {
          setExpandedRowKeys([...expandedRowKeys, record.key]);
        } else {
          const index = expandedRowKeys.indexOf(record.key);
          setExpandedRowKeys([
            ...expandedRowKeys.slice(0, index),
            ...expandedRowKeys.slice(index + 1),
          ]);
        }
      },
      rowExpandable: (record) =>
        record.type === "struct" ||
        record.itemType === "struct" ||
        record.itemType2 === "struct",
    },
  };

  const getExpandedRowKeys = (data: TreeData) => {
    const keys: string[] = [];

    function diff(diffData: TreeData) {
      keys.push(diffData.key);
      diffData.innerFields?.forEach((item) => diff(item));
    }

    diff(data);
    setExpandedRowKeys(keys);
  };

  const initTreeData = useCallback(
    (data: TreeData | Field, key: string): TreeData => {
      if (!props.visible) return treeData;
      const dataTemp: TreeData = data as TreeData;
      dataTemp.key = key;
      dataTemp.innerFields?.forEach((item, i) =>
        initTreeData(item, `${key}-${i}`)
      );
      return dataTemp;
    },
    [props.visible]
  );

  const findTreeNode = (key: string, data: TreeData): TreeData => {
    const path = key.split("-").map((item) => parseInt(item));
    let p = data;
    for (let i = 1; i < path.length; i++) {
      p = p.innerFields[path[i]];
    }
    return p;
  };

  const addTreeNode = (formData: TreeData) => {
    const data = deepClone(formData);
    const cloneData = deepClone(treeData);
    const parentNode = findTreeNode(curEditKey, cloneData);
    if (parentNode.innerFields) {
      parentNode.innerFields.push(data);
    } else {
      parentNode.innerFields = [data];
    }
    initTreeData(parentNode, curEditKey);
    setTreeData(cloneData);

    const length = parentNode.innerFields.length;
    const key = parentNode.innerFields[length - 1].key;
    if (expandedRowKeys.indexOf(key) === -1) {
      setExpandedRowKeys([...expandedRowKeys, key]);
    }
  };

  const editTreeNode = (formData: TreeData) => {
    const data = deepClone(formData);
    // 如果字段原先拥有 innerFields 属性，需要先置为空
    if (
      data.type !== "struct" &&
      data.itemType !== "struct" &&
      data.itemType2 !== "struct" &&
      data.innerFields
    ) {
      // @ts-ignore
      data.innerFields = undefined;
    }

    const cloneData = deepClone(treeData);
    const path = curEditKey.split("-").map((item) => parseInt(item));
    const key = path.slice(0, path.length - 1).join("-");
    const index = path[path.length - 1];

    const parentNode = findTreeNode(key, cloneData);
    const curNode = parentNode.innerFields[path[index]];
    parentNode.innerFields[path[index]] = { ...curNode, ...data };
    setTreeData(cloneData);
  };

  const deleteTreeNode = (curKey: string) => {
    debugger;
    const cloneData = deepClone(treeData);

    const path = curKey.split("-").map((item) => parseInt(item));
    const key = path.slice(0, path.length - 1).join("-");
    const index = path[path.length - 1];

    const parentNode = findTreeNode(key, cloneData);
    parentNode.innerFields.splice(index, 1);
    initTreeData(cloneData, "0");
    setTreeData(cloneData);
    getExpandedRowKeys(cloneData);
  };

  useEffect(() => {
    const data = initTreeData(props.fieldData, "0");
    setTreeData(data);
    // 设置初始的 expandedRowKeys
    getExpandedRowKeys(data);
  }, [props.fieldData, initTreeData]);

  return (
    <>
      <Modal
        title={<div style={{ textAlign: "center" }}>Modify InnerFields</div>}
        visible={props.visible}
        onOk={() => {
          props.onChange(treeData.innerFields);
          props.setVisible(false);
        }}
        onCancel={() => props.setVisible(false)}
        width={800}
      >
        <Table {...tableProps} />
      </Modal>

      <TreeNodeForm
        type={curEditType}
        initData={curEditData}
        visible={curEditVisible}
        setVisible={setCurEditVisible}
        handleOK={(formData) => {
          if (curEditType === "add") {
            addTreeNode(formData as TreeData);
          } else if (curEditType === "edit") {
            editTreeNode(formData as TreeData);
          }
          setCurEditVisible(false);
        }}
      />
    </>
  );
};

export default InnerFieldsTree;
